/******************************************************************************
 * Copyright (C) 2016  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#include "node/util/application.h"
#include <assert.h>
#include <signal.h>
#include <stdio.h>

namespace node {
    namespace util {

    application* application::_this = NULL;
    application::application(const std::string &name)
        : _name(name)
        , _arguments()
        , _options()
    {

    }
    application::~application(void)
    {

    }

    int application::run(int argc, char* argv[])
    {
        int ret_code = 0;
        try {
            if ((ret_code = init(argc, argv)) == 0) {
                ret_code = main(_arguments);
            }
        } catch (const std::exception& e) {
            hanle_exception(e);
        }
        uninit();
        return ret_code;
    }
    void application::show_usage(void)
    {
        printf("%s USAGE\n", _name.c_str());
        for (option_set::const_iterator iter = _options.begin(),
                     iter_end = _options.end(); iter != iter_end; ++iter)
        {
            printf("    --%s,\t-%s\t%8s\t\t%s\n",
                   iter->get_name().c_str(),
                   iter->get_short_name().c_str(),
                   iter->has_argument() ? "argument" : "",
                   iter->get_description().c_str()
            );
        }
        printf("\n");

    }
    bool application::hook_signal(int signal)
    {
        return (::signal(signal, &application::signal_handler) != SIG_ERR);
    }
    bool application::ignore_signal(int signal)
    {
        return (::signal(signal, SIG_IGN) != SIG_ERR);
    }
    bool application::reset_signal(int signal)
    {
        return (::signal(signal, NULL) != SIG_ERR);
    }

    int application::init(int argc, char* argv[])
    {
        for (int argn = 1; argn < argc; ++argn) {
            _arguments.push_back(argv[argn]);
        }
        on_def_options(_options);
        _options.process(_arguments);
        for (option_set::const_iterator iter = _options.begin()
             , iter_end = _options.end();
                iter != iter_end; ++iter)
        {
            if (!iter->is_valid()) {
                if (iter->is_requried()) {
                    return -1;
                }
                continue;
            }

            if (0 != on_option(iter->get_name(), iter->get_value())) {
                return -1;
            }
        }
        return on_init();
    }
    void application::uninit(void)
    {
        on_uninit();
    }
    void application::signal_handler(int signal)
    {
        assert(_this);
        _this->on_signal(signal);
    }
}}
